/**
 * 
 */
package org.nyblom.riskcalc.calculate.impl;

import org.nyblom.riskcalc.calculate.ICalculator;

/**
 * @author qw4z1
 * 
 */
public class BaseCalculator implements ICalculator {

	private int[] mainForces;
	//Attacker and defender index in the mainForces array
	private int attacker = 0;
	private int defender = 1;

	public BaseCalculator() {
		mainForces = new int[2];
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.nyblom.riskcalc.calculate.ICalculator#calculate(int[])
	 */
	public int[] calculate(int[] forces) {
		//Forces not null
		if (forces != null) {
			//One of the forces not is null
			if (forces[defender] > 0 && forces[attacker] > 0) {
				//set forces 
				mainForces = forces;
				//While there are forces left on any side
				while (mainForces[attacker] != 0 && mainForces[defender] != 0) {
					//One attacker left
					if (mainForces[attacker] == 1) {
						calculateOne();
					//Two attackers left
					} else if (mainForces[attacker] == 2) {
						calculateTwo();
					//Three attackers left
					} else {
						calculateThree();
					}
				}
			}
		} else 
			mainForces = new int[]{13,37};
		return mainForces;
	}

	/**
	 * Metod for calculating one attacker
	 */
	private void calculateOne() {
		int[] a = DiceRoller.roll(1);
		int[] d;
		// If defender has or two units left only one die is allowed
		if (mainForces[defender] == 1 || mainForces[defender] == 2) {
			oneDefenderDice(a);
		} else {
			d = DiceRoller.roll(2);
			if (a[0] <= d[0] || a[0] <= d[1]) {
				killAttackers(1);
			} else {
				killDefenders(1);
			}
		}

	}

	private void calculateTwo() {
		int[] a = DiceRoller.roll(2);
		int[] d;
		// If defender has or two units left only one die is allowed
		if (mainForces[defender] == 1 || mainForces[defender] == 2) {
			oneDefenderDice(a);
		} else {
			twoDefenderDice(a);
		}

	}

	private void calculateThree() {
		int[] a = DiceRoller.roll(3);

		// If defender has or two units left only one die is allowed
		if (mainForces[defender] == 1 || mainForces[defender] == 2) {
			oneDefenderDice(a);
		} else {
			twoDefenderDice(a);
		}

	}

	/**
	 * Calculates the outcome with three or more defenders
	 * @param attacker the attacking forces dice
	 */
	public void twoDefenderDice(int[] attacker){
		int[] d = DiceRoller.roll(2);
		
		/*Check first attacker dice against first defender dice and
		 * second attacker dice against second defender dice
		 */
		if (attacker[attacker.length - 1] <= d[1] && attacker[attacker.length -2 ] <= d[0]) {
			killAttackers(2);
		} else if (attacker[2] > d[1] && attacker[1] > d[0]) {
			killDefenders(2);
		} else {
			killAttackers(1);
			killDefenders(1);
		}
	}
	/**
	 * Calculates the outcome with one or two defenders
	 * @param attacker
	 */
	public void oneDefenderDice(int[] attacker){
		int[] d = DiceRoller.roll(1);
		if (attacker[attacker.length -1] <= d[0]) {
			killAttackers(1);
		} else {
			killDefenders(1);
		}
	}
	
	/**
	 * Kill a number of defenders
	 */
	private void killDefenders(int i) {
		mainForces[defender] -= i;
	}

	/**
	 * Kill a number of attackers
	 */
	private void killAttackers(int i) {
		mainForces[attacker] -= i;
	}

}
